// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This file is part of CodingEditor.
// Note:	This project is derived from Peter Project
//			(hosted on sourceforge and codeplex)
//
// Copyright (c) 2008-2009, CE Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


namespace CE.Classes
{
	using System;
	using System.Drawing;
	using System.Runtime.InteropServices;
	using System.Text;
	using System.Windows.Forms;

	using CE.API;

	using mshtml;

    // TODO: Make single class HtmlTooTip and HTMLToolTipForm

	public sealed class HtmlToolTip
	{
		#region Fields

		private const int HWND_TOPMOST = -1;
		private const int SWP_NOACTIVATE = 0x0010;
		private const int SW_SHOWNOACTIVATE = 4;

		private string m_HTML;
		private ICEHtml m_Parent;
		private Form m_Shadow;
		private bool m_Showing;
		private Timer m_Timer;
		private HtmlToolTipForm m_ToolTip;

		#endregion Fields

		#region Constructors

		public HtmlToolTip(ICEHtml parent)
		{
			Startup(parent);
		}

		public HtmlToolTip(string html, Point location, ICEHtml parent)
		{
			Startup(parent);
			HTML = html;
			m_ToolTip.Location = location;
		}

		#endregion Constructors

		#region Properties

		/// <summary>
		/// Get or Sets the Delay of the Tool Tip
		/// </summary>
		public int Delay
		{
			get { return m_Timer.Interval; }

			set{
				if (m_Timer.Enabled) {
					m_Timer.Stop();
				}
				m_Timer.Interval = value;
			}
		}

		/// <summary>
		/// Gets or Sets the HTML of the ToolTip...
		/// </summary>
		public string HTML
		{
			get { return m_HTML; }
			set {
				m_HTML = value;
				var sb = new StringBuilder();
				sb.Append("<html><head><title>ToolTip</title>");
				sb.Append("<style type=\"text/css\">");
				sb.Append(
				        "table {margin:1px;font-family: sans-serif, \"Microsoft Sans Serif\", Arial, Verdana, Tahoma; font-size:75%;}");
				sb.Append("a:link {color:black} a:visited {color:black} a:hover {color:black}");
				sb.Append("ul ul { list-style: none; padding-left: 15px; } ul{ margin-left: 0px; padding: 0px; }");
                sb.Append("span#line { color:green; font-weight:bold;}");
				sb.Append("</style>");
				sb.Append("</head><body style=\"background: white;margin:3px;;font-size:85%\">");
				sb.Append(value);
				sb.Append("</body></html>");
				Doc_HTML = sb.ToString();

                // ffffe1 f0f3f7
			}
		}

		/// <summary>
		/// Gets or Sets the Location of the Tool Tip...
		/// </summary>
		public Point Location
		{
			get { return m_ToolTip.Location; }
			set { m_ToolTip.Location = value; }
		}

		/// <summary>
		/// Gets or Sets if the Tool Tip if Visible...
		/// </summary>
		public bool Visible
		{
			get { return m_ToolTip.Visible; }
			set { m_ToolTip.Visible = value; }
		}

		/// <summary>
		/// Sets the HTML of the document giving the ability to use CSS and scripts.
		/// </summary>
		private string Doc_HTML
		{
			set{
				IHTMLDocument2 doc = (IHTMLDocument2) m_ToolTip.WebBrowser.Document.DomDocument;
				doc.write(value);
				doc.close();
			}
		}

		#endregion Properties

		#region Methods

		/// <summary>
		/// Hides the Tool Tip...
		/// </summary>
		public void Hide()
		{
			var tHide = new Timer {Interval = 10};
			tHide.Tick += tHideTick;
			tHide.Start();
		}

		/// <summary>
		/// Shows the Tool Tip...
		/// </summary>
		public void Show()
		{
			m_Showing = true;
			m_ToolTip.WebBrowser.ScrollBarsEnabled = false;
			m_ToolTip.Height = m_ToolTip.WebBrowser.Document.Body.ScrollRectangle.Height;
			m_ToolTip.Width = m_ToolTip.WebBrowser.Document.Body.ScrollRectangle.Width;

			int left = m_ToolTip.Location.X;
			int top = m_ToolTip.Location.Y;

			if (m_ToolTip.Height > 500) {
				m_ToolTip.Height = 500;
				m_ToolTip.WebBrowser.ScrollBarsEnabled = true;
			}

			if (m_Timer.Enabled) {
				m_Timer.Stop();
			}

			if (Screen.PrimaryScreen.Bounds.Right < (left + m_ToolTip.Width))
				left = Screen.PrimaryScreen.Bounds.Right - m_ToolTip.Width - 5;
			if (Screen.PrimaryScreen.Bounds.Bottom < (top + m_ToolTip.Height))
				top = Screen.PrimaryScreen.Bounds.Bottom - m_ToolTip.Height - 5;

			m_Timer.Start();

			m_ToolTip.Opacity = 0;
			m_Shadow.Opacity = 0;
			m_Shadow.Show();

			SetWindowPos(m_Shadow.Handle.ToInt32(), HWND_TOPMOST, left + 3,
			             top + 3, m_ToolTip.Width, m_ToolTip.Height, SWP_NOACTIVATE);
			ShowWindow(m_Shadow.Handle.ToInt32(), SW_SHOWNOACTIVATE);

			SetWindowPos(m_ToolTip.Handle.ToInt32(), HWND_TOPMOST, left,
			             top, m_ToolTip.Width, m_ToolTip.Height, SWP_NOACTIVATE);
			ShowWindow(m_ToolTip.Handle.ToInt32(), SW_SHOWNOACTIVATE);
			//this.m_ToolTip.Show();

			var tShow = new Timer {Interval = 20};
			tShow.Tick += tShowTick;
			tShow.Start();
		}

		[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
		private static extern bool SetWindowPos(
		        int hWnd, // handle to window
		        int hWndInsertAfter, // placement-order handle
		        int X, // horizontal position
		        int Y, // vertical position
		        int cx, // width
		        int cy, // height
		        uint uFlags // window-positioning options
		        );

		[DllImport("User32")]
		private static extern int ShowWindow(int hwnd, int nCmdShow);

		private void Document_Click(object sender, HtmlElementEventArgs e)
		{
			if (m_Parent != null) {
				if (m_ToolTip.WebBrowser.Document.ActiveElement.TagName.Equals("A")) {
					m_Parent.LinkClick(m_ToolTip.WebBrowser.Document.ActiveElement);
					m_Shadow.Hide();
					m_ToolTip.Hide();
				}
			}
		}

		private void Shadow_GotFocus(object sender, EventArgs e)
		{
			m_ToolTip.Focus();
		}

		private void Startup(ICEHtml parent)
		{
			m_Showing = false;
			m_ToolTip = new HtmlToolTipForm();
			if (m_ToolTip.WebBrowser != null) {
				m_ToolTip.WebBrowser.Navigate("about:Blank");
				while (m_ToolTip.WebBrowser.Document.Body == null) Application.DoEvents();
				m_ToolTip.WebBrowser.Document.Click += Document_Click;
			}
			m_Timer = new Timer {Interval = 5000};
			m_Timer.Tick += TimerTick;
			m_Parent = parent;

			m_Shadow = new Form {ShowInTaskbar = false, FormBorderStyle = FormBorderStyle.None, BackColor = Color.Black};
			m_Shadow.GotFocus += Shadow_GotFocus;
		}

		private void TimerTick(object sender, EventArgs e)
		{
			if (!m_ToolTip.CanClose()) {
				m_Shadow.Hide();
				m_ToolTip.Hide();
				m_Timer.Stop();
			}
		}

		private void tHideTick(object sender, EventArgs e)
		{
			if (m_Showing) {
				var t = (Timer) sender;
				t.Stop();
				return;
			}
			if (m_ToolTip.Opacity <= 0) {
				var t = (Timer) sender;
				t.Stop();
				m_Shadow.Hide();
				m_ToolTip.Hide();
			} else {
				m_Shadow.Opacity -= .10;
				m_ToolTip.Opacity -= .20;
			}
		}

		private void tShowTick(object sender, EventArgs e)
		{
			if (m_ToolTip.Opacity >= 1) {
				var t = (Timer) sender;
				t.Stop();
				m_Showing = false;
			} else {
				m_ToolTip.Opacity += .10;
				m_Shadow.Opacity += .05;
			}
		}

		#endregion Methods
    }

    public sealed class HtmlToolTipForm : Form
    {
        #region Constructors

        public HtmlToolTipForm()
		{
			InitializeComponent();
		}

		#endregion Constructors

		#region Properties

		/// <summary>
		/// Gets or Sets the WebBrowser Control...
		/// </summary>
		public WebBrowser WebBrowser
		{
			get { return webBrowser; }
		}

		protected override bool ShowWithoutActivation
		{
			get { return true; } // base.ShowWithoutActivation;
		}

		#endregion Properties

		#region Methods

		public bool CanClose()
		{
			return DesktopBounds.Contains(MousePosition);
		}

		#endregion Methods
        
        #region Designer

        #region Fields

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.IContainer components = null;

        private System.Windows.Forms.WebBrowser webBrowser;

		#endregion Fields

		#region Methods

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
		protected override void Dispose(bool disposing)
		{
			if (disposing && (components != null)) {
				components.Dispose();
			}
			if(!base.IsDisposed)
				base.Dispose(disposing);
		}

		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.webBrowser = new System.Windows.Forms.WebBrowser();
            this.SuspendLayout();
            // 
            // webBrowser
            // 
            this.webBrowser.AllowNavigation = false;
            this.webBrowser.AllowWebBrowserDrop = false;
            this.webBrowser.Dock = System.Windows.Forms.DockStyle.Fill;
            this.webBrowser.IsWebBrowserContextMenuEnabled = false;
            this.webBrowser.Location = new System.Drawing.Point(0, 0);
            this.webBrowser.MinimumSize = new System.Drawing.Size(20, 20);
            this.webBrowser.Name = "webBrowser";
            this.webBrowser.ScriptErrorsSuppressed = true;
            this.webBrowser.ScrollBarsEnabled = false;
            this.webBrowser.Size = new System.Drawing.Size(202, 49);
            this.webBrowser.TabIndex = 0;
            // 
            // fHtmlToolTip
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.BackColor = System.Drawing.SystemColors.Info;
            this.ClientSize = new System.Drawing.Size(202, 49);
            this.ControlBox = false;
            this.Controls.Add(this.webBrowser);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
            this.Name = "fHtmlToolTip";
            this.ShowIcon = false;
            this.ShowInTaskbar = false;
            this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
            this.ResumeLayout(false);

		}

		#endregion Methods

        #endregion
	}
}